import { logger, tools, runtime } from "./tools.js";

/**基础模块 */
class LayVmodelBase {
    /**绑定元素 */
    element = null;
    vm = {};
    /**
     * 组件传值方向，可选值：all|toValue|fromValue,分别表示 vm,组件双向传值|只传值到vm|只从vm接收值
     * @type {"all"|"toValue"|"fromValue"}
     */
    transDirection = "all"; //传值方向

    constructor(elem) {
        var tis = this;
        this.element = elem;
        this.vm.disabled = ko.observable(false);
        this.form = $(elem).parents(".layui-form")[0];
        this.formFilter = $(this.form).attr("lay-filter") || null;
        this.name = $(elem).attr("name") || null;
        this.layFilter = $(elem).attr("lay-filter") || null;
        this.eHashid = tools.hash.hashCode(elem);
        this.inited = false;

        this.viewModelInit(); //初始化vmodel
        this.loadForAttr(); //从原始dom设置数据  
    }

    /**[virtual] 初始化 */
    init() {
        if (this.inited) return false;
        let tis = this;
        this.vm.disabled.subscribe((newValue) => tis.onDisabledChange(newValue), null, "change");
        this.inited = true;
        return true;
    }

    /**[virtual]  可用性改变 */
    onDisabledChange(disabled) {
        let tis = this;
        if (disabled === this.vm.disabled()) return;

        if (layui.v < '2.7.0') {
            throw new Error("layCheckBox的disabled属性不支持layui版本小于2.7.0");
        }
        //定向渲染
        $(tis.element).prop("disabled", disabled);

        let form = tools.laymod('form');
        form.render($(tis.element));
    }

    /**[virtual]  从原始dom设置数据 */
    loadForAttr() {
        let elem = this.element;
        let vm = this.vm;
        vm.disabled($(elem).prop("disabled"));
    }

    /**[virtual] 初始化vmodel */
    viewModelInit() {
        this.vm.disabled = ko.observable(false);
    }

    /**检测 */
    checkFormFilter() {
        if (!this.form) {
            throw new Error("表单元素必须在layui-form下");
        }
        if (!this.formFilter) {
            logger.logDebug(this.form.tagName + "元素没有lay-filter属性，将自动生成");
            let cmpid = tools.cmpId('layform');
            $(this.form).attr("lay-filter", cmpid);
            this.formFilter = cmpid;
        }
        return true;
    }

    /**没有name则生成name */
    ensureName() {
        let elem = this.element;
        if (!$(elem).attr("name")) {
            logger.logDebug(elem.tagName + "元素没有lay-filter属性，将自动生成");
            let cmpid = tools.cmpId('name');
            $(elem).attr("name", cmpid);
            this.name = cmpid;
        }
        return $(elem).attr("name");
    }

    /**没有lay-filter则生成Filter */
    ensureFilter() {
        let elem = this.element;
        if (!$(elem).attr("lay-filter")) {
            logger.logDebug(elem.tagName + "元素没有lay-filter属性，将自动生成");
            let cmpid = tools.cmpId('layfilter');
            $(elem).attr("lay-filter", cmpid);
            this.layFilter = cmpid;
        }
        return $(elem).attr("lay-filter");
    }

    /**关联设置Vmodel项 */
    regVItem(key, value) {
        var tis = this;
        var vm = this.vm;

        let setKv = function (k, accessor) {
            let isobs = typeof accessor === 'function';
            let accessorValue = isobs ? ko.unwrap(accessor) : accessor;
            let val = vm[k];
            if (val == void 0) return;
            if (val === accessor) return;

            if (["all", "fromValue"].indexOf(tis.transDirection) > -1 || k === "disabled") {
                //判断是否是数组
                if (Array.isArray(accessorValue)) {
                    val([...accessorValue]);
                }
                else {
                    val(accessorValue);
                }
            }

            if (isobs) {
                //双值数据绑定
                if (["all", "toValue"].indexOf(tis.transDirection) > -1 || k === "disabled") {
                    val.subscribe((newValue) => {
                        if(Array.isArray(newValue)){
                            if(tools.arrayEquals(newValue, accessor())) return;
                            accessor([...newValue]);
                        }
                        else{
                            if(newValue === accessor()) return;
                            accessor(newValue);
                        }            
                        
                    }, null, "change");
                }

                if (["all", "fromValue"].indexOf(tis.transDirection) > -1 || k === "disabled") {
                    accessor.subscribe((newValue) => {
                        if(Array.isArray(newValue)){
                            if(tools.arrayEquals(newValue, val())) return;
                            val([...newValue]);
                        }
                        else{
                            if(newValue === val()) return;
                            val(newValue);
                        }                                                
                    }, null, "change");
                }
            }
        }

        if (typeof key === 'object') {
            for (let k in key) {
                setKv(k, key[k]);
            }
        }
        else if (typeof key === 'string') {
            setKv(key, value);
        }
        else {
            throw new Error("参数key 必须是string或object");
        }
    }

    /**销毁*/
    dispose() {
        if (this.obs) {
            this.obs.disconnect();
            this.obs = null;
        }
    }
}

export default LayVmodelBase;

// Path: src\models\LayVmodel.js